package com.sunday.common.easy.excel.config;

import com.sunday.common.core.constants.LogConstants;
import com.sunday.common.core.remoting.rest.annotation.OpenApi;
import com.sunday.common.core.remoting.rest.annotation.VoErrorShowType;
import com.sunday.common.core.remoting.rest.response.RestExceptionResponse;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * @Description: Rest 日志输出及用户绑定
 * <p>
 * 绑定用户 - 默认实现 :
 * 1. Rest层请求日志/响应日志(包含B/C及异常转换)
 * 2. 绑定当前登录人信息(com.sunday.framework.config.mvc.userinfo.CurrentUserHolder)
 * 3. 绑定Web参数 编译/解析策略 （LocalDateTime 格式统一 /Long 精度丢失）
 * 4. 绑定Web交互全局异常拦截
 */
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "sunday.framework.rest", value = "execution")
public class DefaultRestAdvisor {

    @Bean
    public Advisor restPointcutAdvisor(@Value("${sunday.framework.rest.execution}") String execution) {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(execution);
        return new DefaultPointcutAdvisor(pointcut, (MethodInterceptor) invocation -> {
            Method method = invocation.getMethod();
            //获取方法上可能产生的注解
            VoErrorShowType voErrorShowType = method.getAnnotation(VoErrorShowType.class);
            OpenApi openApi = method.getAnnotation(OpenApi.class);
            try {
                /** 请求信息 日志打印 */
                log.info(LogConstants.request_format_aop,
                        Arrays.stream(invocation.getArguments()).map(String::valueOf).collect(Collectors.joining(",")),
                        method.getDeclaringClass(),
                        method.getName());

                /** 执行方法 */
                Object response = invocation.proceed();
                /** 响应信息 日志打印 */
                log.info(LogConstants.response_format_ack, response);
                return response;
            } catch (Throwable e) {
                return RestExceptionResponse.returnResponse(e, voErrorShowType);
            } finally {

            }
        });
    }

}
